package org.dragonnova.meetingclient.core.manager;

import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;

import org.dragonnova.meetingclient.R;
import org.dragonnova.meetingclient.client.service.WIFIConnectionFactory;
import org.dragonnova.meetingclient.client.service.WIFIService;
import org.dragonnova.meetingclient.core.message.GroupMessage;
import org.dragonnova.meetingclient.core.message.Message;
import org.dragonnova.meetingclient.core.message.MessageBuilder;
import org.dragonnova.meetingclient.core.net.SocketUtils;
import org.dragonnova.meetingclient.core.net.socket.NetWorker;
import org.dragonnova.meetingclient.core.net.socket.UdpPacket;
import org.dragonnova.meetingclient.core.net.socket.UdpSocket;
import org.dragonnova.meetingclient.model.AObservable;
import org.dragonnova.meetingclient.model.IObserver;
import org.dragonnova.meetingclient.model.bean.DeviceInfo;
import org.dragonnova.meetingclient.model.bean.VoiceInfo;
import org.dragonnova.meetingclient.utils.ConfigUtil;
import org.dragonnova.meetingclient.utils.Constants;
import org.dragonnova.meetingclient.utils.LogUtil;
import org.dragonnova.meetingclient.utils.PromptUtil;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Created by hucn on 2016/6/7.
 * Description:
 */
public class UdpManager implements NetManager {

    private static final String TAG = UdpManager.class.getName();

    /**
     * 应答机制 允许录音，不允许录音，服务端已经停止
     */
    public final static String KEY_VOICE_RESPONSE_PERMIT = "PERMIT";
    public final static String KEY_VOICE_RESPONSE_PREVENT = "PREVENT";
    public final static String KEY_VOICE_RESPONSE_FINISH = "FINISH";
    /**
     * 用于广播：监听，连接中，已连接，断开连接
     */
    public final static String KEY_GROUP_CONNECTING_STATUS = "CONNECTING";
    public final static String KEY_GROUP_CONNECTED_STATUS = "CONNECTED";
    public final static String KEY_GROUP_DISCONNECT_STATUS = "DISCONNECT";
    /**
     * 服务端语音改变成功
     */
    public final static String KEY_LANGUAGE_CHANGED = "LANGUAGE_CHANGE_SUCESS";
    public final static String KEY_HANDLER_ORG_VOICE_TEXT_ERROR = "org.dragonnova.wifihs.action.ORG_VOICE_TEXT_ERROR";
    public final static String INTENT_TRANSFER_VOICE_DATA = "TRANSFER_VOICE_DATA";
    public final static String KEY_HANDLER_ORG_VOICE_DATA = "org.dragonnova.wifihs.action.ORG_VOICE_DATA";

    /**
     * 传递的数据内容
     */
    private static final int KEY_ACTION_GROUP_NO_JOIN = 0xBB;
    private static final int KEY_ACTION_GROUP_ALLOW_JOIN = 0xAA;
    private static final int KEY_ACTION_GROUP_JOINED = 0xDD;
    private static final byte KEY_ACTION_GROUP_CONFIRM_1 = (byte) 0xEE;
    private static final byte KEY_ACTION_GROUP_JOIN_REQUEST = (byte) 0xCC;
    private static final byte KEY_ACTION_GROUP_CONFIRM_2 = (byte) 0xFF;
    private static final int KEY_ACTION_TRANSFER_VOICE_DATA = 0x10;
    private static final byte KEY_ACTION_GROUP_EXIT = (byte) 0x99;
    private static final int KEY_ACTION_GROUP_CONNECTED_REQUEST = 0x01;
    private static final int KEY_ACTION_GROUP_CONNECTED_RESPONSE = 0x02;
    private static final int KEY_ACTION_GROUP_RECEIVE_ERROR = 0x33;
    private static final int KEY_ACTION_VOICE_REQUEST_START = 0x03;
    private static final int KEY_ACTION_VOICE_REQUEST_STOP = 0x04;
    private static final int KEY_ACTION_VOICE_REQUEST_PERSIST = 0x08;
    private static final int KEY_ACTION_VOICE_RESPONSE_PERMIT = 0x05;
    private static final int KEY_ACTION_VOICE_RESPONSE_PREVENT = 0x06;
    private static final int KEY_ACTION_VOICE_RESPONSE_FINISH = 0x07;
    private static final int KEY_ACTION_VOICE_RESPONSE_PERSIST = 0x09;
    private static final int KEY_ACTION_GROUP_CHANGE_LANGUAGE = 0x31;
    private static final int KEY_ACTION_GROUP_CHANGE_LANGUAGE_COMPLETE = 0x32;
    private static final int KEY_ACTION_DEVICE_REQUEST = 0x35;
    private static final int KEY_ACTION_DEVICE_RESPONSE = 0x36;
    private static final int KEY_ACTION_DEVICE_CHANGE_REQUEST = 0x37;
    private static final int KEY_ACTION_DEVICE_CHANGE_RESPONSE_SUCCESS = 0x38;

    private static final String KEY_ACTION_EXIT = "EXIT";
    private static final String KEY_ACTION_JOIN_REQUEST = "REQUEST";
    /**
     * 用于组网状态标识：监听，连接中，已经连接，断开连接，没有网络状态
     */
    public final static int GROUP_WIFI_NOT_CORRECT_STATUS = 0;
    public final static int GROUP_CONNECTING_STATUS = 1;
    public final static int GROUP_CONNECTED_STATUS = 2;
    public final static int GROUP_DISCONNECTED_STATUS = 3;
    /**
     * 多播地址
     */
    // private final static String MULTICAST_NETWORK_IP = "239.255.255.250";
    private final static String MULTICAST_NETWORK_IP = "224.0.0.1";
    /**
     * 多播端口
     */
    private final static int MULTICAST_NETWORK_PORT = 25221;
    /**
     * 本地UDP通信端口
     */
    private final static int CLIENT_SOCKET_PORT = 24535;
    /**
     * 本地UDP通信端口
     */
    private final static int CLIENT_SOCKET_PORT_BEAT = 24357;
    /**
     * 本地UDP通信端口
     */
    private final static int CLIENT_SOCKET_PORT_VOICE_REQUEST = 24355;
    /**
     * UDP通信端口
     */
    private final static int SERVER_SOCKET_PORT = 30002;
    /**
     * UDP通信端口
     */
    private final static int SERVER_SOCKET_PORT_BEAT = 30001;
    /**
     * UDP通信端口
     */
    private final static int SERVER_SOCKET_PORT_VOICE_REQUEST = 30000;
    /**
     * 组播IP
     */
    private InetSocketAddress mMulticastInetAddr;
    /**
     * 多播线程
     */
    public MulticastSendThread multicastSendWorker;
    /**
     * 组网接收线程
     */
    public MulticastRecThread multicastRecWorker;
    /**
     * 当前wifi组网状态
     */
    public int mCurrentGroupStatus;
    /**
     * UDP服务端IP
     */
    private String UDP_SERVER_IP;
    /**
     * 语音地址、心跳地址、说话请求地址
     */
    private SocketAddress mServerAddr;
    private SocketAddress mBeatAddr;
    private SocketAddress mVoiceReqAddr;
    /**
     * 多播锁
     */
    private WifiManager.MulticastLock multicastLock;
    /**
     * mContext
     */
    private Context mContext;
    /**
     * mWifiManager
     */
    private WifiManager mWifiManager;
    /**
     * 队列上限
     */
    private final static int VOICE_MAX_QUEUE_SIZE = 200;
    /**
     * 用于应答机制的队列
     */
    private LinkedBlockingQueue<Integer> voiceReqQueue = new LinkedBlockingQueue<>(VOICE_MAX_QUEUE_SIZE);
    /**
     * 用于注册监听器
     */
    private WIFIConnectionFactory factory = WIFIConnectionFactory.getInstance();
    /**
     * UDP语音接收和发送线程
     */
    public UdpWorker udpWorker;
    /**
     * 心跳包线程
     */
    public BeatWorker beatWorker;
    /**
     * 说话请求线程
     */
    public VoiceReqWorker voiceReqWorker;
    /**
     * 组网包发送间隔时间
     */
    private int WIFI_GROUP_SEND_THREAD_INTERVAL_TIME;
    private int WIFI_GROUP_SEND_THREAD_INTERVAL_TIME_1;

    private MainThread mMainThread;

    private boolean isStart = false;

    public UdpManager(Context context, WifiManager wifiManager) {
        mContext = context;
        mWifiManager = wifiManager;
        //观察者，拿到网络数据之后发送给MainActivity进行合成
        factory.getObservable().addObserver(new WIFIObserver());

        WIFI_GROUP_SEND_THREAD_INTERVAL_TIME = mContext.getResources().getInteger(R.integer.wifi_group_thread_send_interval);
        WIFI_GROUP_SEND_THREAD_INTERVAL_TIME_1 = mContext.getResources().getInteger(R.integer.wifi_group_thread_send_interval_1);
    }

    @Override
    public void start() {
        startMain();
        isStart = true;
    }

    @Override
    public void stop() {
        mCurrentGroupStatus = GROUP_DISCONNECTED_STATUS;
        multicastUnLock();
        stopAllThreadAndSocket();
        isStart = false;
    }

    @Override
    public void enbleNetWorker() {
        /*if (mCurrentGroupStatus != GROUP_CONNECTED_STATUS) {
            synchronized (mMainThread) {
                mMainThread.notify();
            }
        }*/
    }

    @Override
    public void disableNetWorker() {
        /*mCurrentGroupStatus = GROUP_WIFI_NOT_CORRECT_STATUS;
        stopAllThreadAndSocket();*/
    }

    @Override
    public void tryGroup() {
        // TODO: 2016/6/7 接口还需要设计
    }

    @Override
    public void tryDisGroup() {
        // TODO: 2016/6/7 接口还需要设计
        sendExitPacket();
    }

    @Override
    public boolean isStarted() {
        return isStart;
    }

    @Override
    public void sendVoiceMessage(VoiceInfo voiceInfo) {
        if (mCurrentGroupStatus == GROUP_CONNECTED_STATUS) {
            voiceInfo.setUserId(WIFIService.mLocalDeviceInfo.getHostName());
            if (udpWorker != null) {
                LogUtil.eee(voiceInfo.toString());
                try {
                    udpWorker.sendPacketData(voiceInfo.encode(), new byte[]{KEY_ACTION_TRANSFER_VOICE_DATA});
                } catch (IOException | NullPointerException e) {
                    Log.e(TAG, "BTServiceAidl Send Udp Package Error. " + e.getMessage());
                }
            }
        }
    }

    @Override
    public void changeServerLanguage(char language) {
        if (mCurrentGroupStatus == GROUP_CONNECTED_STATUS) {
            byte[] dataStr = getDeviceInfoPacket();
            try {
                multicastRecWorker.sendPacketData(dataStr, new byte[]{KEY_ACTION_GROUP_CHANGE_LANGUAGE});
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void requestVoiceStart() {
        if (mCurrentGroupStatus == GROUP_CONNECTED_STATUS && voiceReqWorker != null) {
            try {
                voiceReqQueue.put(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            Intent intent = new Intent();
            intent.setAction(Constants.WIFI_BORADCAST_ACTION);
            intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PREVENT);
            mContext.sendBroadcast(intent);
        }
    }

    @Override
    public void requestVoicePersist() {
        if (mCurrentGroupStatus == GROUP_CONNECTED_STATUS && voiceReqWorker != null) {
            try {
                voiceReqQueue.put(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            Intent intent = new Intent();
            intent.setAction(Constants.WIFI_BORADCAST_ACTION);
            intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PREVENT);
            mContext.sendBroadcast(intent);
        }
    }

    @Override
    public void requestVoiceStop() {
        if (mCurrentGroupStatus == GROUP_CONNECTED_STATUS && voiceReqWorker != null) {
            try {
                voiceReqQueue.put(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            voiceReqWorker.requestStop();
        } else {
            Intent intent = new Intent();
            intent.setAction(Constants.WIFI_BORADCAST_ACTION);
            intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_FINISH);
            mContext.sendBroadcast(intent);
        }
    }

    /**
     * 主线程，初始化WIFI连接，组播，服务端SOCKET
     */
    private class MainThread extends Thread {
        private boolean waitFlag = true;

        @Override
        public void run() {

            while (waitFlag) {
                try {
                    synchronized (this) {
                        wait();
                    }
                    startMulti();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                SystemClock.sleep(5000);
            }
        }

        public void close() {
            multicastUnLock();
        }

        public void setFlag(boolean flag) {
            this.waitFlag = flag;
        }
    }

    /**
     * 组网发送线程
     */
    private class MulticastSendThread extends Thread {
        private boolean waitFlag = true;

        @Override
        public void run() {
            this.setName(MulticastRecThread.class.getName());
            Log.i(TAG, "Multicast Socket Send Thread Start.");
            while (waitFlag) {
                // 当前的服务端信息是否存在
                Intent intent = new Intent();
                intent.setAction(Constants.WIFI_BORADCAST_ACTION);
                if (mCurrentGroupStatus != GROUP_CONNECTED_STATUS) {
                    try {
                        Log.i(TAG, "Multicast Socket Send Message.");
                        multicastRecWorker.sendMessage(getPacketByType(KEY_ACTION_JOIN_REQUEST));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_GROUP_DISCONNECT_STATUS);
                    mContext.sendBroadcast(intent);
                }

                if (isNetGroupConnected()) {
                    SystemClock.sleep(WIFI_GROUP_SEND_THREAD_INTERVAL_TIME_1);
                } else {
                    SystemClock.sleep(WIFI_GROUP_SEND_THREAD_INTERVAL_TIME);
                }
            }
        }

        public void setFlag(boolean flag) {
            this.waitFlag = flag;
        }
    }

    /**
     * 组网接收线程
     */
    private class MulticastRecThread extends NetWorker {

        public MulticastRecThread(UdpSocket udpSocket) {
            super(udpSocket);
        }

        private void doHandlerInPacket(UdpPacket packet) {
            int type = SocketUtils.byte2Int(packet.getMessage().getAction());
            DatagramPacket inPacket = packet.getPacket();
            Intent intent;
            Log.i(TAG, "Multicast receive Data from Remote: " + packet.getSocketAddress());
            switch (type) {
                case KEY_ACTION_GROUP_NO_JOIN:
                    try {
                        sendPacketData(new byte[0], new byte[]{KEY_ACTION_GROUP_CONFIRM_1});
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    intent = new Intent();
                    intent.setAction(Constants.WIFI_BORADCAST_ACTION);
                    intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_GROUP_CONNECTING_STATUS);
                    mContext.sendBroadcast(intent);
                    //sendBroadcast(new Intent(KEY_GROUP_CONNECTING_STATUS));
                    break;
                case KEY_ACTION_GROUP_ALLOW_JOIN:
                    try {
                        byte[] dataStr = getDeviceInfoPacket();
                        sendPacketData(dataStr, new byte[]{KEY_ACTION_GROUP_CONFIRM_2});
                        mCurrentGroupStatus = GROUP_CONNECTING_STATUS;
                        intent = new Intent();
                        intent.setAction(Constants.WIFI_BORADCAST_ACTION);
                        intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_GROUP_CONNECTING_STATUS);
                        mContext.sendBroadcast(intent);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                case KEY_ACTION_GROUP_JOINED:
                    Log.e(TAG, "Client Device Connected Server");

                    String serverAddress = SocketUtils.convertIntIpAddress(SocketUtils.byte2Int(((InetSocketAddress) inPacket.
                            getSocketAddress()).getAddress().getAddress()));
                    if (UDP_SERVER_IP == null || !serverAddress.equals(UDP_SERVER_IP)) {
                        UDP_SERVER_IP = serverAddress;
                        //变更服务端地址
                        mServerAddr = new InetSocketAddress(UDP_SERVER_IP, SERVER_SOCKET_PORT);
                        mBeatAddr = new InetSocketAddress(UDP_SERVER_IP, SERVER_SOCKET_PORT_BEAT);
                        mVoiceReqAddr = new InetSocketAddress(UDP_SERVER_IP, SERVER_SOCKET_PORT_VOICE_REQUEST);
                    }
                    mCurrentGroupStatus = GROUP_CONNECTED_STATUS;
                    intent = new Intent();
                    intent.setAction(Constants.WIFI_BORADCAST_ACTION);
                    intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_GROUP_CONNECTED_STATUS);
                    mContext.sendBroadcast(intent);
                    PromptUtil.poolPlay(mContext, R.raw.wifi_grouped);
                    startNetWorkers();
                    break;
                case KEY_ACTION_GROUP_CHANGE_LANGUAGE_COMPLETE:
                    intent = new Intent();
                    intent.setAction(Constants.WIFI_BORADCAST_ACTION);
                    intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_LANGUAGE_CHANGED);
                    mContext.sendBroadcast(intent);
                    break;
                case KEY_ACTION_DEVICE_REQUEST:
                    LogUtil.eee("request the name of the host ");
                    try {
                        byte[] msg = getDeviceInfoPacket();
                        sendPacketData(msg, new byte[]{KEY_ACTION_DEVICE_RESPONSE}, packet.getSocketAddress());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                case KEY_ACTION_DEVICE_CHANGE_REQUEST:
                    LogUtil.eee("request change the name of the host ");
                    Message packetMessage = packet.getMessage();
                    if (packetMessage.getPacketDataLength() > 0) {
                        String msg1 = new String(packetMessage.getPacketData());
                        DeviceInfo info = DeviceInfo.parse(msg1);
                        LogUtil.eee(WIFIService.mLocalDeviceInfo.getHostId() + "==========================" + info.getHostId());
                        if (WIFIService.mLocalDeviceInfo.getHostId().equals(info.getHostId())) {
                            WIFIService.mLocalDeviceInfo.setHostName(info.getHostName());
                            // 保存到本地
                            ConfigUtil.saveClientName(info.getHostName());
                            // 通知客户端，返回已经改变过的地址
                            try {
                                byte[] msg = getDeviceInfoPacket();
                                sendPacketData(msg, new byte[]{KEY_ACTION_DEVICE_CHANGE_RESPONSE_SUCCESS}, packet.getSocketAddress());
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    break;
                default:
                    Log.i(TAG, "Multicast unknown action " + packet.getSocketAddress());
                    break;
            }
        }

        @Override
        public void work() {
            Log.i(TAG, "MultiCast Socket Receive Thread Start. ");
            //客户端组播包 由ID和IP组成
            while (waitFlag) {
                try {
                    UdpPacket packet = receiveMessage(UdpSocket.PACKET_BUFFER_SIZE);
                    if (packet.hasData()) {
                        doHandlerInPacket(packet);
                    } else
                        LogUtil.i(TAG, "receive Data Is Non");
                } catch (IOException e) {
                    Log.e(TAG, "Error: ", e);
                }
            }
        }
    }

    /**
     * 用于维护客户端数据传输
     */
    public class UdpWorker extends NetWorker {

        public UdpWorker(UdpSocket udpSocket) {
            super(udpSocket);
        }

        @Override
        public void work() {
            while (waitFlag && isConnected()) {
                try {
                    UdpPacket packet = receiveMessage(UdpSocket.PACKET_BUFFER_SIZE);
                    Log.i(TAG, " Starting Receiving Udp Message..");
                    if (packet.hasData()) {
                        Log.i(TAG, "UdpWorker Receive Data from Remote: "
                                + ((InetSocketAddress) packet.getSocketAddress()).getHostName());
                        int action = SocketUtils.byte2Int(packet.getMessage().getAction());
                        switch (action) {
                            case KEY_ACTION_TRANSFER_VOICE_DATA:
                                factory.getObservable().handler(packet);
                                break;
                            default:
                                LogUtil.iii("receive incorrect message with unknown action");
                                break;
                        }
                    } else
                        Log.i(TAG, " receive Data Is Null or Length 0");
                } catch (Exception e) {
                    Log.e(TAG, " Error: ", e);
                }
            }
        }
    }

    /**
     * WIFI观察者
     */
    public class WIFIObserver implements IObserver {

        @Override
        public void doWhat(AObservable object, Object... args) {
            //播放语音
            UdpPacket packet = (UdpPacket) args[0];
            String msg = new String(packet.getMessage().getPacketData());
            LogUtil.eee("receive json =========" + msg);
            VoiceInfo voiceInfo = VoiceInfo.parse(msg);

            Intent intent = new Intent();
            intent.setAction(Constants.WIFI_BORADCAST_ACTION);
            if (!TextUtils.isEmpty(voiceInfo.getTranContent())) {
                intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_HANDLER_ORG_VOICE_DATA);
                intent.putExtra(INTENT_TRANSFER_VOICE_DATA, voiceInfo);
            } else {
                intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_HANDLER_ORG_VOICE_TEXT_ERROR);
            }
            mContext.sendBroadcast(intent);
        }
    }

    /**
     * 用于检查网络状况
     */
    class BeatWorker extends NetWorker {
        private int disconnectionCount = 0;

        public BeatWorker(UdpSocket udpSocket) {
            super(udpSocket);
        }

        @Override
        public void work() {
            while (waitFlag && isConnected()) {
                try {
                    byte[] dataStr = getDeviceInfoPacket();
                    sendPacketData(dataStr, new byte[]{KEY_ACTION_GROUP_CONNECTED_REQUEST});
                    try {
                        UdpPacket inPacket = receiveMessage(UdpSocket.PACKET_BUFFER_SIZE);
                        if (inPacket.hasData()) {
                            Log.i(TAG, "BeatWorker receive Data from Remote: "
                                    + inPacket.getSocketAddress());
                            int type = SocketUtils.byte2Int(inPacket.getMessage().getAction());
                            switch (type) {
                                case KEY_ACTION_GROUP_CONNECTED_RESPONSE:
                                    disconnectionCount = 0;
                                    break;
                            }
                        } else {
                            Log.i(TAG, "no data received");
                        }
                        SystemClock.sleep(1500);
                    } catch (SocketTimeoutException e) {
                        disconnectionCount++;
                        Log.i(TAG, "socket timeout when beat，disconnectionCount = " + disconnectionCount);
                    }
                    if (disconnectionCount > 10) {
                        mCurrentGroupStatus = GROUP_DISCONNECTED_STATUS;
                        stopNetWorkers();
                        disconnectionCount = 0;
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 用于维护客户端数据传输
     */
    class VoiceReqWorker extends NetWorker {
        private boolean isReqPermitted = false;
        private boolean isReqStop = false;
        private boolean isReqStart = false;
        private Random random = new Random();

        public VoiceReqWorker(UdpSocket udpSocket) {
            super(udpSocket);
        }

        @Override
        public void work() {
            while (waitFlag && isConnected()) {
                try {
                    int action = voiceReqQueue.take();
                    if (action == 1) {
                        isReqStart = true;
                    }
                    if (action == 2) {
                        isReqStop = true;
                    }
                    if (action == 3) {
                        isReqPermitted = true;
                    }
                    if (mCurrentGroupStatus == GROUP_CONNECTED_STATUS) {
                        while (isReqPermitted || isReqStart || isReqStop) {
                            isReqStart = false;
                            isReqStop = false;
                            isReqPermitted = false;
                                        /*String dataStr = getDeviceInfoPacket();
                                        sendPacketData(dataStr.getBytes(), action);*/
                            int reqIdentify = random.nextInt();
                            sendPacketData(SocketUtils.int2byte(reqIdentify), action);
                            LogUtil.eee(" voice input request:" + "request is " + action);
                            try {
                                while (true) {
                                    UdpPacket inPacket = receiveMessage(UdpSocket.PACKET_BUFFER_SIZE);
                                    if (inPacket.hasData()) {
                                        Log.i(TAG, "VoiceReqWorker receive Data from Remote: "
                                                + inPacket.getSocketAddress());
                                        int type = SocketUtils.byte2Int(inPacket.getMessage().getAction());
                                        int resIdentify = SocketUtils.byte2Int(inPacket.getMessage().getPacketData());
                                        if (reqIdentify == resIdentify) {
                                            Log.i(TAG, "request is same with the response in identity");
                                            switch (type) {
                                                case KEY_ACTION_VOICE_RESPONSE_PERMIT:
                                                    Intent intent = new Intent();
                                                    intent.setAction(Constants.WIFI_BORADCAST_ACTION);
                                                    intent.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PERMIT);
                                                    Log.i(TAG, "request is permitted");
                                                    mContext.sendBroadcast(intent);
                                                    break;
                                                case KEY_ACTION_VOICE_RESPONSE_PREVENT:
                                                    Intent intent1 = new Intent();
                                                    intent1.setAction(Constants.WIFI_BORADCAST_ACTION);
                                                    intent1.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PREVENT);
                                                    isReqPermitted = false;
                                                    Log.i(TAG, "request is not permitted");
                                                    mContext.sendBroadcast(intent1);
                                                    break;
                                                case KEY_ACTION_VOICE_RESPONSE_FINISH:
                                                    Intent intent2 = new Intent();
                                                    intent2.setAction(Constants.WIFI_BORADCAST_ACTION);
                                                    intent2.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_FINISH);
                                                    isReqPermitted = false;
                                                    Log.i(TAG, "request is finished");
                                                    mContext.sendBroadcast(intent2);
                                                    break;
                                                case KEY_ACTION_VOICE_RESPONSE_PERSIST:
                                                    LogUtil.eee("voice input request is persist.......");
                                                    break;
                                            }
                                            break;
                                        } else {
                                            Log.i(TAG, "request is not same with the response in identity");
                                            continue;
                                        }
                                    } else {
                                        Log.i(TAG, "no data received");
                                        isReqPermitted = false;
                                        Intent intent6 = new Intent();
                                        intent6.setAction(Constants.WIFI_BORADCAST_ACTION);
                                        intent6.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PREVENT);
                                        mContext.sendBroadcast(intent6);
                                    }
                                    break;
                                }
                            } catch (SocketTimeoutException e) {
                                LogUtil.eee("voice input request is timeout.......");
                                Intent intent3 = new Intent();
                                intent3.setAction(Constants.WIFI_BORADCAST_ACTION);
                                intent3.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PREVENT);
                                isReqPermitted = false;
                                mContext.sendBroadcast(intent3);
                            }
                        }
                    } else {
                        if (isReqStart && isReqPermitted) {
                            Intent intent4 = new Intent();
                            intent4.setAction(Constants.WIFI_BORADCAST_ACTION);
                            intent4.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PREVENT);
                            isReqStart = false;
                            mContext.sendBroadcast(intent4);
                        } else if (isReqStop) {
                            Intent intent5 = new Intent();
                            intent5.setAction(Constants.WIFI_BORADCAST_ACTION);
                            intent5.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_FINISH);
                            isReqStop = false;
                            mContext.sendBroadcast(intent5);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Intent intent7 = new Intent();
                    intent7.setAction(Constants.WIFI_BORADCAST_ACTION);
                    intent7.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PREVENT);
                    mContext.sendBroadcast(intent7);
                } catch (Exception e) {
                    e.printStackTrace();
                    Intent intent8 = new Intent();
                    intent8.setAction(Constants.WIFI_BORADCAST_ACTION);
                    intent8.putExtra(Constants.BORADCAST_INTENT_OPTION, KEY_VOICE_RESPONSE_PREVENT);
                    mContext.sendBroadcast(intent8);
                }
            }
        }

        /**
         * 发送语音包
         */
        public synchronized void sendPacketData(byte[] data, int action) throws IOException {
            if (isConnected()) {
                byte[] actionBytes = null;
                if (action == 1) {
                    actionBytes = new byte[]{KEY_ACTION_VOICE_REQUEST_START};
                } else if (action == 2) {
                    actionBytes = new byte[]{KEY_ACTION_VOICE_REQUEST_STOP};
                } else if (action == 3) {
                    actionBytes = new byte[]{KEY_ACTION_VOICE_REQUEST_PERSIST};
                }
                sendPacketData(data, actionBytes);
            } else {
                LogUtil.eee("UDP Socket Status is " + " , Current Wifi Status: " + mCurrentGroupStatus);
            }
        }

        public void requestStop() {
            isReqPermitted = false;
        }
    }

    /**
     * 加锁
     */
    private synchronized void multicastLock() {
        multicastLock = mWifiManager.createMulticastLock("GROUP LOCK");
        multicastLock.acquire();
    }

    /**
     * 解锁
     */
    private synchronized void multicastUnLock() {
        if (multicastLock != null && multicastLock.isHeld())
            multicastLock.release();
    }

    /**
     * 获取deviceinfo的byte[]
     */
    private byte[] getDeviceInfoPacket() {
        String ipAddr = SocketUtils.convertIntIpAddress(mWifiManager.getConnectionInfo().getIpAddress());
        String wifiMacAddr = mWifiManager.getConnectionInfo().getMacAddress();
        //String hostId, String hostName, String wifiMacAddr, String btMacAddr, String wifiAddr, String btName, char language, int port
        DeviceInfo info = new DeviceInfo(WIFIService.mLocalDeviceInfo.getHostId(), WIFIService.mLocalDeviceInfo.getHostName(), wifiMacAddr, WIFIService.mLocalDeviceInfo.getBtMacAddr(), ipAddr, WIFIService.mLocalDeviceInfo.getBtName(), WIFIService.mLocalDeviceInfo.getLanguage(), WIFIService.mLocalDeviceInfo.getPort());
        return info.encode();
    }

    /**
     * 根据类型生成本机信息通信包
     */
    private UdpPacket getPacketByType(String type) {
        byte[] dataStr = getDeviceInfoPacket();
        MessageBuilder messageBuilder = new MessageBuilder(new GroupMessage());
        if (type.equalsIgnoreCase(KEY_ACTION_EXIT)) {
            messageBuilder.setAction(new byte[]{KEY_ACTION_GROUP_EXIT});
        } else if (type.equalsIgnoreCase(KEY_ACTION_JOIN_REQUEST)) {
            messageBuilder.setAction(new byte[]{KEY_ACTION_GROUP_JOIN_REQUEST});
        } else if (TextUtils.isEmpty(type)) {
            messageBuilder.setAction(new byte[]{KEY_ACTION_GROUP_RECEIVE_ERROR});
        }
        messageBuilder.setDataLength(dataStr.length);
        messageBuilder.setData(dataStr);
        return new UdpPacket().setMessage(messageBuilder.create()).setSocketAddress(mMulticastInetAddr).setDefaultDatagramPacket();
    }

    public void startMain() {
        mMainThread = new MainThread();
        mMainThread.start();
        SystemClock.sleep(1000);
        synchronized (mMainThread) {
            mMainThread.notify();
        }
    }

    public void stopMain() {
        if (mMainThread != null) {
            mMainThread.setFlag(false);
            mMainThread.close();
            mMainThread.interrupt();
        }
    }

    public void startNetWorkers() {
        //监听组网情况的线程
        LogUtil.e(TAG, "NetWorker Thread Start. ");
        int count = 0;
        DatagramSocket beatSocket = null;
        try {
            beatSocket = new DatagramSocket(new InetSocketAddress(
                    WIFIService.mLocalDeviceInfo.getWifiAddr(), CLIENT_SOCKET_PORT_BEAT));
            beatSocket.setSoTimeout(1500);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (beatSocket != null) {
            UdpSocket beatSocket1 = new UdpSocket(beatSocket);
            beatWorker = new BeatWorker(beatSocket1);
            beatWorker.setRequestAddr(mBeatAddr);
            beatWorker.start();
            count++;
            LogUtil.e(TAG, "BeatWorker Thread Start. ");
        }
        //应答机制的线程
        DatagramSocket voiceReqSocket = null;
        try {
            voiceReqSocket = new DatagramSocket(new InetSocketAddress(
                    WIFIService.mLocalDeviceInfo.getWifiAddr(), CLIENT_SOCKET_PORT_VOICE_REQUEST));
            voiceReqSocket.setSoTimeout(1500);

        } catch (IOException e) {
            e.printStackTrace();
        }
        if (voiceReqSocket != null) {
            UdpSocket voiceReqSocket1 = new UdpSocket(voiceReqSocket);
            voiceReqWorker = new VoiceReqWorker(voiceReqSocket1);
            voiceReqWorker.setRequestAddr(mVoiceReqAddr);
            voiceReqWorker.start();
            count++;
            LogUtil.e(TAG, "VoiceReqWorker Thread Start. ");
        }
        //启动UDP语音包接收线程
        DatagramSocket udpSocket = null;
        try {
            udpSocket = new DatagramSocket(new InetSocketAddress(
                    WIFIService.mLocalDeviceInfo.getWifiAddr(), CLIENT_SOCKET_PORT));
        } catch (SocketException e) {
            e.printStackTrace();
        }
        if (udpSocket != null) {
            UdpSocket udpSocket1 = new UdpSocket(udpSocket);
            //客户端组播包 由ID和IP组成
            udpWorker = new UdpWorker(udpSocket1);
            udpWorker.setRequestAddr(mServerAddr);
            udpWorker.start();
            count++;
            LogUtil.e(TAG, "UdpWorker Thread Start. ");
        }
        if (count != 3) {
            LogUtil.e(TAG, "netWorker Thread Start at Count = " + count);
        }
    }

    public void stopNetWorkers() {
        if (udpWorker != null) {
            udpWorker.setFlag(false);
            udpWorker.close();
            udpWorker = null;
        }
        if (beatWorker != null) {
            beatWorker.setFlag(false);
            beatWorker.close();
            beatWorker = null;
        }
        if (voiceReqWorker != null) {
            voiceReqWorker.setFlag(false);
            voiceReqWorker.close();
            voiceReqWorker = null;
            try {
                voiceReqQueue.put(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.gc();
    }

    /**
     * 销毁除了主线程和网络监听线程外的其他线程
     */
    private void stopAllThreadAndSocket() {
        stopMain();
        stopMulti();
        stopNetWorkers();
    }

    private void startAllThreadAndSocket() {
        startMain();
        startMulti();
        stopNetWorkers();
    }

    private void stopMulti() {
        if (multicastSendWorker != null) {
            multicastSendWorker.setFlag(false);
            multicastSendWorker.interrupt();
            multicastSendWorker = null;
        }
        if (multicastRecWorker != null) {
            multicastRecWorker.setFlag(false);
            multicastRecWorker.close();
            multicastRecWorker = null;
        }
    }

    private void startMulti() {
        InetAddress multiInetAddr = null;
        MulticastSocket socket = null;
        UdpSocket multicastSocket = null;
        if (multicastSocket == null || !multicastSocket.isBound()) {
            try {
                multicastLock();
                //启动多播套接字
                socket = new MulticastSocket(MULTICAST_NETWORK_PORT);
                multiInetAddr = InetAddress.getByName(MULTICAST_NETWORK_IP);
                socket.joinGroup(multiInetAddr);
                mMulticastInetAddr = new InetSocketAddress(MULTICAST_NETWORK_IP, MULTICAST_NETWORK_PORT);
                socket.setReuseAddress(true);
                socket.setLoopbackMode(true);
                socket.setTimeToLive(1);
                multicastSocket = new UdpSocket(socket);
                mCurrentGroupStatus = GROUP_DISCONNECTED_STATUS;
                Log.i(TAG, "MulticastSocket Start Join Group ");
            } catch (Exception e) {
                Log.e(TAG, "MulticastSocket IO ERROR: ", e);
                if (socket != null) {
                    try {
                        socket.leaveGroup(multiInetAddr);
                    } catch (IOException e2) {
                        e2.printStackTrace();
                    } finally {
                        socket.close();
                    }
                }
                multicastUnLock();
            }
            //如果多播网络存在的话
            if (multicastSocket != null && multicastSocket.isBound()) {
                try {
                    //启动组网接收线程
                    multicastRecWorker = new MulticastRecThread(multicastSocket);
                    multicastRecWorker.setRequestAddr(mMulticastInetAddr);
                    multicastRecWorker.start();
                    multicastSendWorker = new MulticastSendThread();
                    multicastSendWorker.start();
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
            // SystemClock.sleep(2000);
        }
    }

    /**
     * 是否组网
     */
    private boolean isNetGroupConnected() {
        return UDP_SERVER_IP != null && mServerAddr != null
                && mCurrentGroupStatus == GROUP_CONNECTED_STATUS;
    }

    private boolean isNetGroupConnected2() {
        return UDP_SERVER_IP != null && mServerAddr != null;
    }

    /**
     * 发送退出
     */
    private void sendExitPacket() {
        if (mCurrentGroupStatus == GROUP_CONNECTED_STATUS) {
            if (isNetGroupConnected2()) {
                for (int i = 0; i < 5; i++) {
                    try {
                        multicastRecWorker.sendMessage(getPacketByType(KEY_ACTION_EXIT));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
